package `object`

/**
 *   @author be7364
 *   @description
 *   @datetime 2021/6/11 9:47
 *
 */
class ClassAndObject {

}

// 1. 类定义

// 1.1 空类
class Empty

// 1.2 在类中定义成员函数
class Student() {
    fun greet() {
        println("Hello")
    }
}

// 2. 类的属性

// 2.1 属性定义: 类的属性可以用关键字 var 声明为可变的，否则使用只读关键字 val 声明为不可变。
class Teacher() {
    var name: String = ""
    val type: String = "Teacher"
}

// 主构造器
class Person11 constructor(firstName: String) {}
// 如果主构造器没有任何注解，也没有任何可见度修饰符，那么constructor关键字可以省略
class Person22 constructor(firstName: String) {}
class Person33 private constructor(firstName: String) {}

// 2.2 getter setter
// 如果属性类型可以从初始化语句或者类的成员函数中推断出来，那就可以省去类型，val不允许设置setter函数，因为它是只读的。
class Gt() {
    // Property must be initialized or be abstract
    // var a: Int?
    // 类型为 Int, 默认实现了 getter 和 setter
    var b = 1

    //  类型为 Int 类型,默认实现 getter
    val d = 1
}

class Gt2() {
    // 类型为 Int ，默认实现 getter ，但必须在构造函数中初始化
    //val c:Int?
}

class Gt3() {
    var lastName: String = "zhang"
        get() = field.toUpperCase()
        set

    var no: Int = 100
        get() = field
        set(value) {
            if(value < 10) {
                field = value
            } else {
                field = -1
            }
        }

    var heiht: Float = 180.0F
        private set

}

// 非空属性必须在定义的时候初始化,kotlin提供了一种可以延迟初始化的方案,使用 lateinit 关键字描述属性

// 3.主构造器
// 主构造器中不能包含任何代码，初始化代码可以放在初始化代码段中，初始化代码段使用 init 关键字作为前缀。
class clas constructor(name: String) {
    init {
        println("name = $name")
    }
}

// 次构造器,如果类有主构造函数，每个次构造函数都要，或直接或间接通过另一个次构造函数代理主构造函数。在同一个类中代理另一个构造函数使用 this 关键字
// this 里面的参数名是次级构造函数定义的
class Example(name: String) {
    constructor(age: Int, namename: String) : this(namename) {
        println("次级构造器")
        println("age=$age, name=")
    }
}
//// 必须要定义主构造函数才能定义次级构造函数
//class Example2() {
//    constructor()
//}


// 4. 抽象类
//抽象是面向对象编程的特征之一，类本身，或类中的部分成员，都可以声明为abstract的。抽象成员在类中不存在具体的实现。
//注意：无需对抽象类或抽象成员标注open注解。
open class Base() {
    open fun method() {
        println("fun")
    }
}

abstract class Derived : Base() {
    // 抽象方法不能有实现
    abstract override fun method()
    fun myMethod() {
        println("myMethod")
    }
}

//fun main() {
//    // Cannot create an instance of an abstract class
//    // val a =  Derived()
//
//}

// 5. 嵌套类
class Outer {                  // 外部类
    private val bar: Int = 1
    var v = "vvvvv"
    class Nested {             // 嵌套类
        fun foo() = 2
        // Unresolved reference: bar
        // fun foo2() = bar
        // fun foo3() = v
    }
}

//fun main(args: Array<String>) {
//    val demo = Outer.Nested().foo() // 调用格式：外部类.嵌套类.嵌套类方法/属性
//    println(demo)    // == 2
//}

// 6. 内部类
class Outer2() {
    private var bar: Int = 10

    inner class Inner() {
        fun foo() = bar

        fun foo2() {
            val o = this@Outer2
            println(o.bar)
        }

    }
}


// 7. 匿名内部类
class Test() {
    val v = "vvv"
    fun setInterFace(iFace: TestInterFace) {
        iFace.method();
    }
}

interface TestInterFace {
    fun method()
}

class TestInterFaceImpl() : TestInterFace {
    override fun method() {
        println("hello")
    }

}
/*
fun main() {
    var test = Test()
    test.setInterFace(object : TestInterFace{
        override fun method() {
            println("hi")
        }
    })
    var tfi = TestInterFaceImpl()
    test.setInterFace(tfi)
}
 */

// 8. 类的修饰符
/*

classModifier: 类属性修饰符，标示类本身特性。

abstract    // 抽象类
final       // 类不可继承，默认属性
enum        // 枚举类
open        // 类可继承，类默认是final的
annotation  // 注解类


accessModifier: 访问权限修饰符

private    // 仅在同一个文件中可见
protected  // 同一个文件中或子类可见
public     // 所有调用的地方都可见
internal   // 同一个模块中可见
*/